home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / program / misc / fpl-v13.lha / fpl / src / scan.c < prev    next >
C/C++ Source or Header  |  1995-07-09  |  12KB  |  399 lines

  1. /******************************************************************************
  2.  *                   FREXX PROGRAMMING LANGUAGE                  *
  3.  ******************************************************************************
  4.  
  5.  scan.c
  6.  
  7.  Various program scanning/reading routines.
  8.  
  9.  *****************************************************************************/
  10.  
  11. /************************************************************************
  12.  *                                                                      *
  13.  * fpl.library - A shared library interpreting script langauge.         *
  14.  * Copyright (C) 1992-1994 FrexxWare                                    *
  15.  * Author: Daniel Stenberg                                              *
  16.  *                                                                      *
  17.  * This program is free software; you may redistribute for non          *
  18.  * commercial purposes only. Commercial programs must have a written    *
  19.  * permission from the author to use FPL. FPL is *NOT* public domain!   *
  20.  * Any provided source code is only for reference and for assurance     *
  21.  * that users should be able to compile FPL on any operating system     *
  22.  * he/she wants to use it in!                                           *
  23.  *                                                                      *
  24.  * You may not change, resource, patch files or in any way reverse      *
  25.  * engineer anything in the FPL package.                                *
  26.  *                                                                      *
  27.  * This program is distributed in the hope that it will be useful,      *
  28.  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
  29.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                 *
  30.  *                                                                      *
  31.  * Daniel Stenberg                                                      *
  32.  * Ankdammsgatan 36, 4tr                                                *
  33.  * S-171 43 Solna                                                       *
  34.  * Sweden                                                               *
  35.  *                                                                      *
  36.  * FidoNet 2:201/328    email:dast@sth.frontec.se                       *
  37.  *                                                                      *
  38.  ************************************************************************/
  39.  
  40. #ifdef AMIGA
  41. #include <exec/types.h>
  42. #include <dos.h>
  43.  
  44. #elif defined(UNIX)
  45. #include <sys/types.h>
  46. #include <stdio.h>
  47. #endif
  48.  
  49. #include "script.h"
  50. #include "debug.h"
  51.  
  52. static ReturnCode INLINE Eatcomment(struct Data *);
  53.  
  54. /************************************************************************
  55.  *
  56.  * int GetEnd(struct Data *, uchar, uchar, uchar)
  57.  *
  58.  * Makes the current position to be the one right after the character
  59.  * you wanna search for.
  60.  *
  61.  * Returns error code.
  62.  *
  63.  *****/
  64.  
  65. ReturnCode REGARGS
  66. GetEnd(struct Data *scr, /* giant script structure */
  67.        uchar leta,     /* what character you do wanna find */
  68.        uchar motsats,     /* the opposite character do the one above */
  69.        uchar outside)     /* TRUE/FALSE if outside an opposite version */
  70. {
  71.   ReturnCode ret;
  72.   uchar find=1-outside;
  73.   long junk; /* only for the ReturnChar() function */
  74.   long prg=scr->prg;
  75.   uchar *text=scr->text;
  76.   uchar check;
  77.   while(scr->prg<=scr->prog->lines) {
  78.     check=*scr->text;
  79.     if(check==leta) {
  80.       scr->text++;
  81.       if(!--find)
  82.     return(FPL_OK);
  83.     } else if(check==motsats) {
  84.       find++;
  85.       scr->text++;
  86.     } else if(check==CHAR_QUOTATION_MARK) {
  87.       scr->text++;
  88.       if(GetEnd(scr, CHAR_QUOTATION_MARK, (uchar)255, FALSE))
  89.     return(FPLERR_SYNTAX_ERROR); /* missing quotation mark */
  90.     } else if(check==CHAR_APOSTROPHE && leta!=CHAR_QUOTATION_MARK) {
  91.       scr->text++;
  92.       CALL(ReturnChar(scr, &junk, FALSE));
  93.       if(CHAR_APOSTROPHE!=*scr->text++)
  94.     return(FPLERR_MISSING_APOSTROPHE);
  95.     } else if(check==CHAR_ASCII_ZERO) {
  96.       CALL(Newline(scr));
  97.     } else if(leta==CHAR_QUOTATION_MARK && check == CHAR_BACKSLASH) {
  98.       CALL(ReturnChar(scr, &junk, TRUE));
  99.     } else {
  100.       if(check==CHAR_NEWLINE)
  101.     scr->virprg++;
  102.       scr->text++;
  103.       if(leta!=CHAR_QUOTATION_MARK && Eat(scr))
  104.         /* we only call Eat() if this is *not* a string passing! */
  105.     break;
  106.     }
  107.   }
  108.   scr->text=text;
  109.   scr->prg=prg;
  110.   return(FPLERR_MISSING_PARENTHESES);
  111. }
  112.  
  113. /**********************************************************************
  114.  *
  115.  * Getword()
  116.  *
  117.  * Store next word in a buffer. Returns error code!
  118.  *
  119.  *******/
  120.  
  121. ReturnCode REGARGS
  122. Getword(struct Data *scr)
  123. {
  124.   ReturnCode ret;
  125.   uchar len=0;
  126.   uchar *buffer = scr->buf;
  127.   if(ret=Eat(scr))
  128.     ;
  129.   else if(!isident(*scr->text))
  130.     ret=FPLERR_SYNTAX_ERROR; /* non-alpha char found where alpha is supposed */
  131.   else
  132.     do {
  133.       if(len<IDENTIFIER_LEN) {
  134.     /*
  135.      * With the length check above, we can use identifiers with
  136.      * _any_ length. There are only IDENTIFIER_LEN number of
  137.      * significant characters!
  138.      *
  139.      */
  140.     len++;
  141.     *buffer++=*scr->text++;
  142.       }
  143.     } while(isidentnum(*scr->text));
  144.   *buffer=0;
  145.   return(ret);
  146. }
  147.  
  148. /**********************************************************************
  149.  *
  150.  * int Eatcomment(struct Data *);
  151.  *
  152.  * Jumps to the end of the comment we're standing on.
  153.  *
  154.  *******/
  155.  
  156. static ReturnCode INLINE Eatcomment(struct Data *scr)
  157. {
  158.   ReturnCode ret;
  159.   long nums=0;
  160.   scr->text+=2;
  161.   while(scr->prg<=scr->prog->lines) {
  162.     switch(scr->text[0]) {
  163.     case CHAR_MULTIPLY:
  164.       if(scr->text[1]==CHAR_DIVIDE) {
  165.     scr->text+=2;
  166.         if(nums--)
  167.           break;
  168.     return(FPL_OK);
  169.       } else
  170.     scr->text++;
  171.       break;
  172.     case CHAR_ASCII_ZERO:
  173.       CALL(Newline(scr));
  174.       break;
  175.     case CHAR_NEWLINE:
  176.       scr->text++;
  177.       scr->virprg++; /* stepped down another virutal line! */
  178.       break;
  179.     case CHAR_DIVIDE:
  180.       if(scr->flags&FPLDATA_NESTED_COMMENTS && scr->text[1]==CHAR_MULTIPLY) {
  181.         nums++;
  182.         scr->text+=2;
  183.         break;
  184.       }
  185.     default:
  186.       scr->text++;
  187.       break;
  188.     }
  189.   }
  190.   return(FPLERR_UNBALANCED_COMMENT);
  191. }
  192.  
  193. /**********************************************************************
  194.  *
  195.  * int Eat(struct Data *);
  196.  *
  197.  * This eats all whitespaces, new lines and comments
  198.  *
  199.  * Returns error code.
  200.  *
  201.  *******/
  202.  
  203. ReturnCode REGARGS
  204. Eat(struct Data *scr)
  205. {
  206.   ReturnCode ret;
  207.   uchar new=0;
  208.   while(1) {
  209.     switch(*scr->text) {
  210.     case CHAR_NEWLINE:
  211.       scr->text++;
  212.       scr->virprg++; /* stepped down another virutal line! */
  213.       new=1;
  214.       break;
  215.     case CHAR_ASCII_ZERO:
  216.       CALL(Newline(scr));
  217.       /* This really confuses our virtual line counter! */
  218.       new=1;
  219.       break;
  220.     case CHAR_HASH:
  221.       if(new) {
  222.     /* This is the first 'real' character after a newline! That means
  223.        this could be a valid #line-instruction! */
  224.     scr->text++; /* pass the hash */
  225.     if(!Getword(scr)) {
  226.           /* there was a word following the hash sign! */
  227.  
  228.       if(!strcmp(scr->buf, "line")) {
  229.             /* 'line' instruction! */
  230.             scr->virprg=Strtol(scr->text, 10, &scr->text); /* get number */
  231.             Eat(scr); /* get whitespace */
  232.             if(*scr->text==CHAR_QUOTATION_MARK) {
  233.               /* we have a new virtual file name! */
  234.               scr->virfile=scr->text++; /* just point to this text! */
  235.               if(GetEnd(scr, CHAR_QUOTATION_MARK, 255, FALSE))
  236.                 return FPLERR_SYNTAX_ERROR;
  237.               Eat(scr);
  238.             }
  239.             break;
  240.           }
  241.       if(!strcmp(scr->buf, "pragma")) {
  242.             /* 'pragma' instruction! */
  243.             Getword(scr); /* get the following word */
  244.             if(!strcmp(scr->buf, "nocache")) {
  245.               /*
  246.                * The pragma 'nocache' marks this file to get flushed
  247.                * from memory as fast as not in use
  248.                */
  249.               scr->prog->flags |= PR_FLUSH_NOT_IN_USE;
  250.               break;
  251.             }
  252.             if(!strcmp(scr->buf, "cache")) {
  253.               /*
  254.                * The pragma 'cache' marks this file to *not* get flushed
  255.                * from memory when not in use
  256.                */
  257.               scr->prog->flags &= ~PR_FLUSH_NOT_IN_USE;
  258.               break;
  259.             }
  260.             if(!strcmp(scr->buf, "reread")) {
  261.               /*
  262.                * The pragma 'reread' marks this file to get reread into
  263.                * memory when accessed and the actual file is changed on disk
  264.                */
  265.               scr->prog->flags |= PR_REREAD_CHANGES;
  266.               break;
  267.             }
  268.             if(!strcmp(scr->buf, "noreread")) {
  269.               /*
  270.                * The pragma 'noreread' marks this file to *not* get reread
  271.                * into memory when accessed and the actual file is changed
  272.                * on disk
  273.                */
  274.               scr->prog->flags &= ~PR_REREAD_CHANGES;
  275.               break;
  276.             }
  277.             /* no supported pragma was found, eat the rest of the line as
  278.                usual in this case */
  279.           }
  280.       while (*++scr->text!=CHAR_NEWLINE);
  281.         }
  282.       } else
  283.     return(FPL_OK);
  284.       break;
  285.     case CHAR_DIVIDE:
  286.       if(scr->text[1]==CHAR_MULTIPLY) {
  287.     CALL(Eatcomment(scr));
  288.       } else if(scr->text[1]==CHAR_DIVIDE)
  289.     while (*++scr->text && *scr->text!=CHAR_NEWLINE);
  290.       else
  291.     return(FPL_OK);
  292.       new=0;
  293.       break;
  294.     default:
  295.       if(!isspace(*scr->text))
  296.     return(FPL_OK);
  297.       scr->text++;
  298.       new=0;
  299.       break;
  300.     }
  301.   }
  302. }
  303.  
  304. /*********************************************************************
  305.  *
  306.  * Newline()
  307.  *
  308.  * This routine gets called everytime the interpreter finds an ASCII
  309.  * zero in the program. This is made like this for future version which
  310.  * will be able to specify programs in several ways. (Not only the
  311.  * array and continues memory alternatives!)
  312.  *
  313.  *****/
  314.  
  315. ReturnCode REGARGS
  316. Newline(struct Data *scr)
  317. {
  318.   if(scr->prg<scr->prog->lines) {
  319.     scr->text=(&scr->prog->program)[scr->prg++];
  320.     return(FPL_OK);
  321.   } else
  322.     return(FPLERR_UNEXPECTED_END);
  323. }
  324.  
  325.  
  326. ReturnCode REGARGS ScanForNext(struct Data *scr,
  327.                                Operator op) /* previous operator */
  328. {
  329.   long val=0;
  330.   long junk;
  331.   ReturnCode ret;
  332.   while( !( ret = Eat(scr) ) ) {
  333.     if(ispunct(scr->text[0])) {
  334.       switch(scr->text[0]) {
  335.       case CHAR_OPEN_PAREN:
  336.     CALL(GetEnd(scr, CHAR_CLOSE_PAREN, CHAR_OPEN_PAREN, TRUE));
  337.     continue;
  338.       case CHAR_OPEN_BRACKET:
  339.     if(GetEnd(scr, CHAR_CLOSE_BRACKET, CHAR_OPEN_BRACKET, TRUE))
  340.           return FPLERR_MISSING_BRACKET;
  341.     continue;
  342.       case CHAR_SEMICOLON:
  343.       case CHAR_CLOSE_PAREN:
  344.       case CHAR_CLOSE_BRACKET:
  345.  
  346.       case CHAR_OPEN_BRACE:  /* these two are very wrong if they appear! */
  347.       case CHAR_CLOSE_BRACE:
  348.  
  349.     /* done, return to base */
  350.     return FPL_OK;
  351.     break;
  352.       case CHAR_QUOTATION_MARK:
  353.     if(GetEnd(scr, CHAR_QUOTATION_MARK, 255, FALSE))
  354.           return FPLERR_SYNTAX_ERROR;
  355.     break;
  356.       case CHAR_AND:
  357.     break;
  358.       case CHAR_OR:
  359.     if(CHAR_OR == scr->text[1]) {
  360.       if(OP_LOGAND == op) {
  361.         /* we have to stop here! */
  362.         return FPL_OK;
  363.       }
  364.     }
  365.     break;
  366.       case CHAR_APOSTROPHE:
  367.     /*
  368.      * Eat this properly!!!
  369.      */
  370.     scr->text++;
  371.     CALL(ReturnChar(scr, &junk, FALSE));
  372.     if(CHAR_APOSTROPHE!=*scr->text++)
  373.       return(FPLERR_MISSING_APOSTROPHE);
  374.     continue;
  375.       case CHAR_QUESTION:
  376.     if(OP_LOGAND == op ||
  377.        OP_LOGOR == op)
  378.       return FPL_OK;
  379.     if(OP_COND1 == op)
  380.       val++;    /* remember there was an extra '?' !! */
  381.     break;
  382.       case CHAR_COLON:
  383.     if(OP_COND1 == op) {
  384.       if(!val--)    /* don't forget if there were any extra '?' !! */
  385.         return FPL_OK;
  386.     }
  387.     break;
  388.       case CHAR_COMMA:
  389.     return FPL_OK;
  390.       }
  391.       scr->text++;
  392.     }
  393.     else {
  394.       while(!ispunct(*scr->text))
  395.     scr->text++;
  396.     }
  397.   }
  398. }
  399.